package org.bao.netcrawler.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.bao.netcrawler.policy.model.Policy;
import org.bao.netcrawler.policy.model.Target;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * 
 * parse xml files into informations wanted(Policy objects).
 * @author Bao<bb@feijiao.info>
 * @since 2010-12-24
 * @version 0.9.0
 * @license GPLv3
 */
public class XMLParser {
	public static final String XML_ATTR_NAME_ID = "id";
	public static final String XML_ATTR_NAME_FORMAT = "format";
	public static final String XML_NODE_NAME_POLICIES = "policies";
	public static final String XML_NODE_NAME_POLICY = "policy";
	public static final String XML_NODE_NAME_URL = "url";
	public static final String XML_NODE_NAME_TARGETS = "targets";
	public static final String XML_NODE_NAME_TARGET = "target";
	public static final String XML_NODE_NAME_POSTION = "position";
	public static final String XML_NODE_NAME_CHARACTER = "character";
	
	
	private String filepath = null;
	
	public XMLParser(String filepath){
		this.filepath = filepath;
	}
	
	
	public ArrayList<Policy> parse(){
		try {
			return this.parse(new FileInputStream(new File(this.filepath)));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//BAD DATA FILE
		Info.type = Info.INFO_TYPE_BAD_DATA_FILE;
		return null;
	}
	
	private ArrayList<Policy> parse(InputStream is){
		ArrayList<Policy> policies = new ArrayList<Policy>();
		Policy policy = null;
		Target target = null;
		String position = null;
		String character = null;
		
		
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder;
		Document document;
		
		try {
			builder = factory.newDocumentBuilder();
			System.err.println(is == null);
			document = builder.parse(is);
			
			Element element = document.getDocumentElement();
			
			NodeList nodes = element.getElementsByTagName(XMLParser.XML_NODE_NAME_POLICY);
			
			for(int i = 0; i < nodes.getLength(); i++){
				Element e = (Element)nodes.item(i);
				
				NodeList children = e.getChildNodes();
								
				for(int j = 0; j < children.getLength(); j++){
					Node node = children.item(j);
					
					if(node.getNodeName().equals(XMLParser.XML_NODE_NAME_URL)){
						//System.err.println("info@XMLParser>" + e.getAttribute(XMLParser.XML_ATTR_NAME_FORMAT));
						policy = new Policy(e.getAttribute(XMLParser.XML_ATTR_NAME_FORMAT), node.getFirstChild().getNodeValue());
					}
					else
					if(node.getNodeName().equals(XMLParser.XML_NODE_NAME_TARGETS)){
						NodeList grandchildren = ((Element)node).getChildNodes();
						
						for(int k = 0; k < grandchildren.getLength(); k++){
							
							if(grandchildren.item(k).getNodeName().equals(XMLParser.XML_NODE_NAME_TARGET)){
								NodeList endNode = ((Element)grandchildren.item(k)).getChildNodes();
								
								for(int q = 0 ; q < endNode.getLength(); q++){
									if(endNode.item(q).getNodeName().equals(XMLParser.XML_NODE_NAME_POSTION)){
										position = endNode.item(q).getFirstChild().getNodeValue();
									}
									else
									if(endNode.item(q).getNodeName().equals(XMLParser.XML_NODE_NAME_CHARACTER)){
										character = endNode.item(q).getFirstChild().getNodeValue();
									}
								}
								target = new Target(((Element)grandchildren.item(k)).getAttribute(XMLParser.XML_ATTR_NAME_ID), position, character);
								
								policy.addTarget(target);
							}
						}
					}
				}
				
				policies.add(policy);
				
			}
			
			return policies;
			
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return null;
	}
}
